#ifndef UL_PIPE_TASK_QUEUE_H_ 
#define UL_PIPE_TASK_QUEUE_H_
#include "ul_task_queue.h"
#include "ul_define.h"
#include "ul_malloc.h"
#include <poll.h>
namespace LinuxNetworkUtility
{
  class UlPipeMultiProducerSingleConsumerTQ : public UlMultiProducerSingleConsumerTskQueue
  {
  public:
    UlPipeMultiProducerSingleConsumerTQ();
    virtual ~UlPipeMultiProducerSingleConsumerTQ();

    virtual void* malloc_tsk(const int64_t size, const int32_t mod_id)
    {
      return ul_malloc(size,mod_id,NULL,FREE_TO_ALLOCATED_THREAD_POOL);
    }

    virtual void free_tsk(void* tsk)
    {
      ul_free(tsk);
    }

    virtual int init(const int64_t producer_num);
    virtual int push(const void *tsk, const int64_t producer_id);
    virtual int pop(void **tsk, const int64_t ntsk, const int64_t timeout_us);
  private:
    void clear();
    struct _PipeFds
    {
      int32_t read_fd_;
      int32_t write_fd_;
    };
    struct _FdPair
    {
      int32_t fd_[2];
    };
    union PipeFdPairs
    {
      _PipeFds pipe_fds_;
      _FdPair  fd_pair_;
    };
    PipeFdPairs fd_pair_;
  };

  class UlPipeQueenWorkerTQ
  {
  public:
    UlPipeQueenWorkerTQ();
    virtual ~UlPipeQueenWorkerTQ();

    virtual void* malloc_tsk(const int64_t size, const int32_t mod_id)
    {
      return ul_malloc(size,mod_id,NULL,FREE_TO_ALLOCATED_THREAD_POOL);
    }

    virtual void free_tsk(void* tsk)
    {
      ul_free(tsk);
    }

    virtual int init(const int64_t worker_bee_num);
    /// the queen bee dispatch task to worker bees
    virtual int dispatch_task(void *tsk);
    /// the worker bee claim task to do
    virtual int claim_task(void **tsk, const int64_t ntsk, 
                           const int64_t timeout_us, const int64_t worker_id);
    /// the worker bee submit output of task
    virtual int submit_output(void *tsk, const int64_t worker_id);
    /// the queen bee fetch output of tasks
    virtual int fetch_output(void **tsk, const int64_t ntsk, const int64_t timeout_us);
  private:
    void clear();
    struct _PipeFds
    {
      int32_t worker_fd_;
      int32_t queen_fd_;
    };
    struct _FdPair
    {
      int32_t fd_[2];
    };
    union PipeFdPairs
    {
      _PipeFds pipe_fds_;
      _FdPair  fd_pair_;
    };
    int64_t     next_push_pipe_idx_;
    int64_t     consumer_num_;
    PipeFdPairs     *fd_pairs_;
    struct pollfd   *queen_poll_fds_;
  };
}
#endif /* UL_PIPE_TASK_QUEUE_H_ */
